package com.me.collector;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g2d.ParticleEffectPool.PooledEffect;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.Shape;
import com.badlogic.gdx.physics.box2d.World;
import com.me.collector.Definitions.EntityCategory;

public class FallingObject{

	//****************************
	//Members
	//****************************
	
	private FallingObjectList fObjectList;
	private Physics physics;
	private Sprite sprite;
	private TextureRegion textureRegion;
	private BodyDef bodyDef;
	private Body body;
	private Item item;
	private boolean pause = false;
	private boolean removeable = false;

   //****************************
   // Constructors
   //****************************	
	public FallingObject(FallingObjectList fObjectList, Vector2 startPosition)
	{
		this.fObjectList = fObjectList;
		physics = fObjectList.getPhysics();
		item = fObjectList.getItem();
		sprite = new Sprite(fObjectList.getItem().getTexture());
		
		sprite.setSize(fObjectList.getItem().getWidth(), fObjectList.getItem().getHeight());
		sprite.setOrigin(0, 0);
		
		bodyDef = new BodyDef();
		bodyDef.type = BodyType.DynamicBody;
		bodyDef.position.set(startPosition.x * Definitions.WORLD_TO_BOX, startPosition.y * Definitions.WORLD_TO_BOX);
		
		body = fObjectList.getWorld().createBody(bodyDef);
		body.setUserData(item);
		
		// Deal with all shapes
		ArrayList<Shape> shapes = fObjectList.getItem().createShapes();
		for(Shape s: shapes)
		{
			FixtureDef f = new FixtureDef();
			f.shape = s;
			f.density = this.physics.getDensity();
			f.friction = this.physics.getFriction();
			f.restitution = this.physics.getRestitution();
			f.filter.categoryBits = fObjectList.getItem().getCategory();
			f.filter.maskBits = fObjectList.getItem().getMask();
		
			body.createFixture(f);
		}
	}
	
	// Create FallingObject with random start position
	public FallingObject(FallingObjectList fObjectList)
	{
		this(fObjectList, createRandomStartPosition(fObjectList.getItem().getWidth(), fObjectList.getItem().getHeight()));
	}
	
    //****************************
    // Methods
    //****************************
	
	public void dispose()
	{
		body.getWorld().destroyBody(body);
	}
	
	public void update() {
		// Make sure the game is not paused, otherwise
		// the linear impulse will wake up the body
		if(pause == false)
		{
			body.applyLinearImpulse(new Vector2(getWindFactor(), 0), body.getPosition());		
		}
				
		float newAngle = body.getAngle() * MathUtils.radiansToDegrees;
		sprite.setPosition((body.getPosition().x * Definitions.BOX_TO_WORLD), (body.getPosition().y * Definitions.BOX_TO_WORLD));
		sprite.setRotation(newAngle);
	}
	
	public void draw(SpriteBatch batch)
	{
		sprite.draw(batch);
	}
	
	public void pause()
	{
		pause = true;
		body.setAwake(false);
	}
	
	public void resume()
	{
		pause = false;
		body.setAwake(true);
	}
	
	private static Vector2 createRandomStartPosition(int textureWidth, int textureHeight)
	{	
		int x, y, maxWidth;
		Vector2 startposition;
		Random r;
		
		r = new Random();

		maxWidth = Definitions.SCREEN_WIDTH - textureWidth;
		
		y = Definitions.SCREEN_HEIGHT + textureHeight;
		x = r.nextInt(maxWidth - textureWidth + 1) + textureWidth;
		
		startposition = new Vector2(x, y);
		
		return startposition;
	}
	
	/* Divide screen in 4 equal parts
	 * and calculate a factor for the wind
	 */
	private float getWindFactor()
	{
		int frameSize = Definitions.SCREEN_HEIGHT / 4;
		float currentYPos = body.getPosition().y;
		int currentframe;
		float movement;
		
		if(currentYPos <= frameSize)
		{
			movement = 2;
		}
		else if(currentYPos <= frameSize * 2)
		{
			movement = 5;
		}
		else if(currentYPos <= frameSize * 3)
		{
			movement = 10;
		}
		else
		{
			movement = 20;
		}
		movement = movement * physics.getWind();
		
		return movement;
	}
	
	public void remove()
	{
		removeable = true;
	}
	
	
	//****************************
	// Properties
	//****************************
	
	public FallingObjectList getFObjectList()
	{
		return fObjectList;
	}
	
	public Body getBody()
	{
		return body;
	}
	
	public Sprite getSprite()
	{
		return sprite;
	}
	
	public Item getItem()
	{
		return item;
	}

	public Vector2 getPosition() {
		return new Vector2(sprite.getX(), sprite.getY());
	}
	
	public boolean isRemoveable()
	{
		return removeable;
	}
}
